package com.huicheng.ui;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.huicheng.Utils.Utils;
import com.huicheng.service.*;
import android.app.Activity;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.huicheng.R;
import com.huicheng.service.BluetoothLeService;


public class Ble_Activity extends Activity implements OnClickListener , AdapterView.OnItemSelectedListener {

	private final static String TAG = "BleActivity";
	public static String HEART_RATE_MEASUREMENT = "0000ffe1-0000-1000-8000-00805f9b34fb";
	public static String EXTRAS_DEVICE_NAME = "DEVICE_NAME";;
	public static String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
	public static String EXTRAS_DEVICE_RSSI = "RSSI";
	private boolean mConnected = false;
	private String status = "disconnected";
	private String mDeviceName;
	private String mDeviceAddress;
	private String mRssi;
	private Bundle b;
	private String rev_str = "";
	private static BluetoothLeService mBluetoothLeService;
	private TextView rev_tv, connect_state;
	private Button send_btn;
	private Button cmd_btn;
	private Button clean_send_btn;
	private Button clean_rev_btn;
	private EditText send_et;
	private ScrollView rev_sv;
	private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
	private Spinner cmd_spinner;
	private TextView byte_count_tv;

	private long log_byte_count = 0;

	final String cmd_name_arr[]=new String[]{
			"身份证-获取模块编号",
			"身份证-获取模块状态",
			"身份证-寻找身份证",
			"身份证-选取身份证",
			"身份证-读文字照片信息",
			"指纹-连接设备",
			"指纹-获取版本信息",
			"指纹-获取设备参数",
			"指纹-初始化传感器",
			"指纹-采集上传图像",
			"指纹-采集特征",
			"指纹-上传特征1",
			"指纹-上传特征2",
			"指纹-指纹比对"
	};
	final String cmd_str_arr[]=new String[]{
			"AA AA AA 96 69 00 03 12 FF EE",
			"AA AA AA 96 69 00 03 11 FF ED",
			"AA AA AA 96 69 00 03 20 01 22",
			"AA AA AA 96 69 00 03 20 02 21",
			"AA AA AA 96 69 00 03 30 01 32",
			"5B 00 04 01 00 00 00 05 5D",
			"5B 00 04 01 00 00 00 05 5D",
			"5B 00 04 01 00 00 01 04 5D",
			"5B 00 03 73 00 00 70 5D",
			"5B 00 07 44 00 00 0F 00 00 00 4C 5D",
			"5B 00 06 12 00 00 0A 00 00 1E 5D",
			"5B 00 03 13 00 00 10 5D",
			"5B 00 03 13 00 00 10 5D",
			"5B 00 03 30 00 00 33 5D"
	};
	private static BluetoothGattCharacteristic target_chara = null;
	private Handler mhandler = new Handler();
	private Handler myHandler = new Handler()
	{
		public void handleMessage(Message msg)
		{
			switch (msg.what)
			{
			case 1:
			{
				String state = msg.getData().getString("connect_state");
				connect_state.setText(state);

				break;
			}

			}
			super.handleMessage(msg);
		}

	};

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.ble_activity);
		b = getIntent().getExtras();
		mDeviceName = b.getString(EXTRAS_DEVICE_NAME);
		mDeviceAddress = b.getString(EXTRAS_DEVICE_ADDRESS);
		mRssi = b.getString(EXTRAS_DEVICE_RSSI);
		Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
		bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
		init();
		Log.i(TAG, "hexStr2Bytes onCreate");

	}

	@Override
	protected void onDestroy()
	{
		super.onDestroy();
		unregisterReceiver(mGattUpdateReceiver);
		mBluetoothLeService = null;
	}

	@Override
	protected void onResume()
	{
		super.onResume();
		registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
		if (mBluetoothLeService != null)
		{
			final boolean result = mBluetoothLeService.connect(mDeviceAddress);
			Log.i(TAG, "Connect request result=" + result);
		}
	}

	private void init()
	{
		rev_sv = (ScrollView) this.findViewById(R.id.rev_sv);
		rev_tv = (TextView) this.findViewById(R.id.rev_tv);
		connect_state = (TextView) this.findViewById(R.id.connect_state);
		send_btn = (Button) this.findViewById(R.id.send_btn);
		cmd_btn = (Button)this.findViewById(R.id.send_cmd);
		send_et = (EditText) this.findViewById(R.id.send_et);
		send_et.addTextChangedListener(new CustomTextWatcher(send_et));
		cmd_spinner = (Spinner)this.findViewById(R.id.cmd_spinner);
		SpinnerAdapter arrayAdapter = new SpinnerAdapter(this, android.R.layout.simple_spinner_item, cmd_name_arr);
		cmd_spinner.setAdapter(arrayAdapter);
		cmd_spinner.setOnItemSelectedListener(this);
		connect_state.setText(status);
		send_btn.setOnClickListener(this);
		cmd_btn.setOnClickListener(this);
		send_btn.setFocusable(true);
		send_btn.requestFocus();

		clean_rev_btn = (Button)this.findViewById(R.id.clean_log_btn);
		clean_send_btn = (Button)this.findViewById(R.id.clean_cmd_btn);
		clean_send_btn.setOnClickListener(this);
		clean_rev_btn.setOnClickListener(this);
		log_byte_count = 0;
		byte_count_tv = (TextView)this.findViewById(R.id.byte_count_tv);
		byte_count_tv.setText(Long.toString(log_byte_count));
	}

	private final ServiceConnection mServiceConnection = new ServiceConnection()
	{

		@Override
		public void onServiceConnected(ComponentName componentName,
				IBinder service)
		{
			mBluetoothLeService = ((BluetoothLeService.LocalBinder) service)
					.getService();
			if (!mBluetoothLeService.initialize())
			{
				Log.e(TAG, "Unable to initialize Bluetooth");
				finish();
			}
			mBluetoothLeService.connect(mDeviceAddress);

		}

		@Override
		public void onServiceDisconnected(ComponentName componentName)
		{
			mBluetoothLeService = null;
		}

	};

	private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver()
	{
		@Override
		public void onReceive(Context context, Intent intent)
		{
			final String action = intent.getAction();
			if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action))
			{
				mConnected = true;
				status = "connected";
				//��������״̬
				updateConnectionState(status);
				Log.i(TAG, "BroadcastReceiver :" + "device connected");

			} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED
					.equals(action)) {
				mConnected = false;
				status = "disconnected";
				//��������״̬
				updateConnectionState(status);
				Log.i(TAG, "BroadcastReceiver :"
						+ "device disconnected");

			} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED
					.equals(action)) {
				displayGattServices(mBluetoothLeService
						.getSupportedGattServices());
				Log.i(TAG, "BroadcastReceiver :"
						+ "device SERVICES_DISCOVERED");
			} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action))
			{
				displayData(intent.getExtras().getString(
						BluetoothLeService.EXTRA_DATA));
				Log.i(TAG, "BroadcastReceiver onData:"
						+ intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
			}
		}
	};

	private void updateConnectionState(String status)
	{
		Message msg = new Message();
		msg.what = 1;
		Bundle b = new Bundle();
		b.putString("connect_state", status);
		msg.setData(b);
		myHandler.sendMessage(msg);
		Log.i(TAG, "connect_state:" + status);

	}

	private static IntentFilter makeGattUpdateIntentFilter()
	{
		final IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
		intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
		intentFilter
				.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
		intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
		return intentFilter;
	}

	private void displayData(String rev_string)
	{
		String tmpStr = rev_string;
		log_byte_count += tmpStr.trim().replace(" ","").length()/2;
		byte_count_tv.setText(Long.toString(log_byte_count));
		rev_str += rev_string + "\n";
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				rev_tv.setText(rev_str);
				rev_sv.scrollTo(0, rev_tv.getMeasuredHeight());
				System.out.println("rev:" + rev_str);
			}
		});

	}

	private void displayGattServices(List<BluetoothGattService> gattServices)
	{

		if (gattServices == null)
			return;
		String uuid = null;
		String unknownServiceString = "unknown_service";
		String unknownCharaString = "unknown_characteristic";

		ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();

		ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList<ArrayList<HashMap<String, String>>>();

		mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();

		for (BluetoothGattService gattService : gattServices)
		{

			HashMap<String, String> currentServiceData = new HashMap<String, String>();
			uuid = gattService.getUuid().toString();

			gattServiceData.add(currentServiceData);

			Log.i(TAG,"Service uuid:" + uuid);

			ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList<HashMap<String, String>>();

			List<BluetoothGattCharacteristic> gattCharacteristics = gattService
					.getCharacteristics();

			ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<BluetoothGattCharacteristic>();

			for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics)
			{
				charas.add(gattCharacteristic);
				HashMap<String, String> currentCharaData = new HashMap<String, String>();
				uuid = gattCharacteristic.getUuid().toString();

				if (gattCharacteristic.getUuid().toString()
						.equals(HEART_RATE_MEASUREMENT))
				{
					mhandler.postDelayed(new Runnable()
					{

						@Override
						public void run()
						{
							mBluetoothLeService
									.readCharacteristic(gattCharacteristic);
						}
					}, 200);

					mBluetoothLeService.setCharacteristicNotification(
							gattCharacteristic, true);
					target_chara = gattCharacteristic;
				}
				List<BluetoothGattDescriptor> descriptors = gattCharacteristic
						.getDescriptors();
				for (BluetoothGattDescriptor descriptor : descriptors)
				{
					Log.i(TAG, "---descriptor UUID:"
							+ descriptor.getUuid());
					mBluetoothLeService.getCharacteristicDescriptor(descriptor);
				}

				gattCharacteristicGroupData.add(currentCharaData);
			}
			mGattCharacteristics.add(charas);
			gattCharacteristicData.add(gattCharacteristicGroupData);

		}

	}
	public int[] dataSeparate(int len)
	{   
		int[] lens = new int[2];
		lens[0]=len/20;
		lens[1]=len-20*lens[0];
		return lens;
	}
	
	private boolean sendCmdBuff(byte[] buff)
	{
		if(target_chara == null)
		{
			Toast.makeText(this,"请等待蓝牙连接再发送！",Toast.LENGTH_LONG).show();
			return false;
		}
		int len = buff.length;
		for (int i = 0; i < buff.length; i++) {
			Log.i(TAG,"hexStr2Bytes" + buff[i]);
		}
		int[] lens = dataSeparate(len);
		for (int i = 0; i < lens[0]; i++) {
			byte[] tmp1Bytes = new byte[20];
			for(int j=0;j< 20;j++)
			{
				tmp1Bytes[j] = buff[i*20 + j];
			}
			target_chara.setValue(tmp1Bytes);
			mBluetoothLeService.writeCharacteristic(target_chara);
		}
		if (lens[1] != 0) {
			byte[] tmp2Bytes = new byte[lens[1]];
			for(int j=0;j< lens[1];j++)
			{
				tmp2Bytes[j] = buff[lens[0]*20 + j];
			}
			target_chara.setValue(tmp2Bytes);
			mBluetoothLeService.writeCharacteristic(target_chara);

		}
		return true;
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
			case R.id.send_btn:
				// TODO Auto-generated method stub
				byte[] buff = Utils.hexStr2Bytes(send_et.getText().toString().replaceAll(" ", ""));
				sendCmdBuff(buff);
				break;
			case R.id.send_cmd:
				byte[] buffCmd = Utils.hexStr2Bytes(cmd_str_arr[cmd_spinner.getSelectedItemPosition()].toString().replaceAll(" ", ""));
				sendCmdBuff(buffCmd);
				break;
			case R.id.clean_cmd_btn:
				send_et.setText("");
				break;
			case R.id.clean_log_btn:
				log_byte_count = 0;
				byte_count_tv.setText(Long.toString(log_byte_count));
				rev_str = "";
				rev_tv.setText(rev_str);
				break;
		}
	}
	@Override
	public void onItemSelected(AdapterView<?> parent, View view,
							   int position, long id) {
		Log.i(TAG,"onItemSelected" + position);
	}

	@Override
	public void onNothingSelected(AdapterView<?> parent) {

	}
	private class SpinnerAdapter extends ArrayAdapter<String> {
		Context context;
		String[] items = new String[] {};

		public SpinnerAdapter(final Context context,
							  final int textViewResourceId, final String[] objects) {
			super(context, textViewResourceId, objects);
			this.items = objects;
			this.context = context;
		}

		@Override
		public View getDropDownView(int position, View convertView,
									ViewGroup parent) {

			if (convertView == null) {
				LayoutInflater inflater = LayoutInflater.from(context);
				convertView = inflater.inflate(
						android.R.layout.simple_spinner_item, parent, false);
			}

			TextView tv = (TextView) convertView
					.findViewById(android.R.id.text1);
			tv.setText(items[position]);
			tv.setTextSize(30);
			return convertView;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			if (convertView == null) {
				LayoutInflater inflater = LayoutInflater.from(context);
				convertView = inflater.inflate(
						android.R.layout.simple_spinner_item, parent, false);
			}

			// android.R.id.text1 is default text view in resource of the android.
			// android.R.layout.simple_spinner_item is default layout in resources of android.

			TextView tv = (TextView) convertView
					.findViewById(android.R.id.text1);
			tv.setText(items[position]);
			tv.setTextSize(25);
			tv.setPadding(0,10,0,10);
			return convertView;
		}
	}
	public class CustomTextWatcher implements TextWatcher {

		private static final String TAG = "CustomTextWatcher";

		private boolean mFormat;

		private boolean mInvalid;

		private int mSelection;

		private String mLastText;

		private EditText mEditText;

		public CustomTextWatcher(EditText editText) {

			super();
			mFormat = false;
			mInvalid = false;
			mLastText = "";
			this.mEditText = editText;
			this.mEditText.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
		}

		@Override
		public void beforeTextChanged(CharSequence charSequence, int start,
									  int count, int after) {

		}

		@Override
		public void onTextChanged(CharSequence charSequence, int start, int before,
								  int count) {

			try {

				String temp = charSequence.toString();

				// Set selection.
				if (mLastText.equals(temp)) {
					if (mInvalid) {
						mSelection -= 1;
					} else {
						if ((mSelection >= 1) && (temp.length() > mSelection - 1)
								&& (temp.charAt(mSelection - 1)) == ' ') {
							mSelection += 1;
						}
					}
					int length = mLastText.length();
					if (mSelection > length) {

						mEditText.setSelection(length);
					} else {

						mEditText.setSelection(mSelection);
					}
					mFormat = false;
					mInvalid = false;
					return;
				}

				mFormat = true;
				mSelection = start;

				// Delete operation.
				if (count == 0) {
					if ((mSelection >= 1) && (temp.length() > mSelection - 1)
							&& (temp.charAt(mSelection - 1)) == ' ') {
						mSelection -= 1;
					}

					return;
				}

				// Input operation.
				mSelection += count;
				char[] lastChar = (temp.substring(start, start + count))
						.toCharArray();
				int mid = lastChar[0];
				if (mid >= 48 && mid <= 57) {
                /* 1-9. */
				} else if (mid >= 65 && mid <= 70) {
                /* A-F. */
				} else if (mid >= 97 && mid <= 102) {
                /* a-f. */
				} else {
                /* Invalid input. */
					mInvalid = true;
					temp = temp.substring(0, start)
							+ temp.substring(start + count, temp.length());
					mEditText.setText(temp);
					return;
				}

			} catch (Exception e) {
				Log.i(TAG, e.toString());
			}
		}

		@Override
		public void afterTextChanged(Editable editable) {

			try {

            /* Format input. */
				if (mFormat) {
					StringBuilder text = new StringBuilder();
					text.append(editable.toString().replace(" ", ""));
					int length = text.length();
					int sum = (length % 2 == 0) ? (length / 2) - 1 : (length / 2);
					for (int offset = 2, index = 0; index < sum; offset += 3, index++) {

						text.insert(offset, " ");
					}
					mLastText = text.toString();
					mEditText.setText(text);
				}
			} catch (Exception e) {
				Log.i(TAG, e.toString());
			}
		}

	}
}
